package com.apestech.framework.run.core;

import java.sql.Savepoint;
import java.util.Vector;

import com.apestech.framework.db.SqlSession;
import com.apestech.framework.run.callback.ParamThreadCallBack;
import com.apestech.framework.run.callback.ReadonlyThreadCallBack;
import com.apestech.framework.run.callback.SaveTransactionThreadCallBack;
import com.apestech.framework.run.callback.ThreadCallBackHandler;
import com.apestech.framework.run.callback.TransactionThreadCallBack;
import com.apestech.framework.run.modul.ListParam;
import com.apestech.framework.run.modul.MutiParam;
import com.apestech.framework.run.modul.SingleParam;
import com.apestech.framework.util.ReflectUtil;

public class ParamTask {
	
	public static SingleThread getThread(String name, ThreadCallBackHandler threadCallBackHandler) throws Exception{
		SingleParam param=addTask(name, threadCallBackHandler);
		return getThread(param);
	}
	
	public static SingleThread getDBThread(String dbName, String type, String name, ThreadCallBackHandler threadCallBackHandler) throws Exception{
		SingleParam param=addTask(name, threadCallBackHandler);
		return dbThread(dbName, type, param);
	}
	
	public static SingleThread getThread(String name, String className, String methodName) throws Exception{
		SingleParam param=addTask(name, className, methodName);
		return getThread(param);
	}
	
	public static SingleThread getDBThread(String dbName, String type, String name, String className, String methodName) throws Exception{
		SingleParam param=addTask(name, className, methodName);
		return dbThread(dbName, type, param);
	}
	
	public static SingleThread getThread(String name, String className, String methodName, Object...params) throws Exception{
		SingleParam param=addTask(name, className, methodName, params);
		return getThread(param);
	}
	
	public static SingleThread getDBThread(String dbName, String type, String name, String className, String methodName, Object...params) throws Exception{
		SingleParam param=addTask(name, className, methodName, params);
		return dbThread(dbName, type, param);
	}
	
	protected static SingleThread dbThread(String dbName, String type, SingleParam param) throws Exception{
		switch(type){
			case "saveTransaction":
				return getDbSaveTransactionThread(dbName, param);
			case "readonly":
				return getDbReadOnlyThread(dbName, param);
			default:
				return getDbTransactionThread(dbName, param);
		}
	}
	
	protected static SingleParam addTask(String name, ThreadCallBackHandler threadCallBackHandler){
		SingleParam param=new SingleParam();
    	param.setName(name);
    	param.add(threadCallBackHandler);
    	return param;
	}
	
	protected static SingleParam addTask(String name, String className, String methodName){
    	SingleParam param=new SingleParam();
    	param.setName(name);
    	param.add(className, methodName);
    	return param;
    }
	
	protected static SingleParam addTask(String name, String className, String methodName, Object...params){
    	SingleParam param=new SingleParam();
    	param.setName(name);
    	param.add(className, methodName, params);
    	return param;
    }
	
	protected static SingleThread getThread(final SingleParam param) throws Exception{
		SingleThread thread=null;
		if(param.isCallback()){
			thread=new SingleThread(param.getName(), param.getThreadCallBackHandler());
		} else {
			final Object obj=ReflectUtil.getObject(param.getClassName());
			thread=new SingleThread(param.getName(),new ParamThreadCallBack(param.getParam()){
				protected void run(Vector<Object> p) throws Exception {
					ReflectUtil.execMethod(obj, param.getMethodName(), p);
				}
			});
		}
		return thread;
	}
	
	protected static SingleThread getDbReadOnlyThread(String dbName, final SingleParam param) throws Exception{
		final Object obj=ReflectUtil.getObject(param.getClassName());
		SingleThread thread=new SingleThread(param.getName(),new ReadonlyThreadCallBack(dbName, param.getParam()){
			protected void run(SqlSession cn, Vector<Object> p)
					throws Exception {
				ReflectUtil.execMethod(obj, param.getMethodName(), p);
			}
		});
		return thread;
	}
	
	protected static SingleThread getDbTransactionThread(String dbName, final SingleParam param) throws Exception{
		final Object obj=ReflectUtil.getObject(param.getClassName());
		SingleThread thread=new SingleThread(param.getName(),new TransactionThreadCallBack(dbName, param.getParam()){
			protected void run(SqlSession cn, Vector<Object> p)
					throws Exception {
				ReflectUtil.execMethod(obj, param.getMethodName(), p);
			}
		});
		return thread;
	}
	
	protected static SingleThread getDbSaveTransactionThread(String dbName, final SingleParam param) throws Exception{
		final Object obj=ReflectUtil.getObject(param.getClassName());
		SingleThread thread=new SingleThread(param.getName(),new SaveTransactionThreadCallBack(dbName, param.getParam()){
			protected Savepoint run(SqlSession cn, Vector<Object> p)
					throws Exception {
				return (Savepoint) ReflectUtil.execMethod(obj, param.getMethodName(), p);
			}
		});
		return thread;
	}
	
	//同一个运行线程里包括多个不同调用方法，常用情况最多数，注意该模式下暂不支持带保存点的提交
	public static SingleThread getThread(final MutiParam params){
		final int len=params.size();
		if(len<1) return null;
		Vector<Object> plist=new Vector<Object>();
		plist.add(params.getParam());
		SingleThread thread=new SingleThread(params.getName(),new ParamThreadCallBack(plist){
			protected void run(Vector<Object> arg) throws Exception {
				Vector<SingleParam> p=(Vector<SingleParam>) arg.get(0);
				for(int i=0; i<len; i++){
					SingleParam param=p.get(i);
					if(param.isCallback()){
						param.getThreadCallBackHandler().run();
					} else {
						ReflectUtil.execMethod(param.getClassName(), param.getMethodName(), param.getParam());
					}
				}
			}
		});
		return thread;
	}
	
	public static SingleThread getDBThread(String dbName, String type, MutiParam params){
		switch(type){
			case "readonly":
				return getDbReadOnlyThread(dbName, params);
			default:
				return getDbTransactionThread(dbName, params);
		}
	}
	
	protected static SingleThread getDbReadOnlyThread(String dbName, final MutiParam params){
		final int len=params.size();
		if(len<1) return null;
		Vector<Object> plist=new Vector<Object>();
		plist.add(params.getParam());
		SingleThread thread=new SingleThread(params.getName(),new ReadonlyThreadCallBack(dbName, plist){
			protected void run(SqlSession cn, Vector<Object> arg) throws Exception{
				Vector<SingleParam> p=(Vector<SingleParam>) arg.get(0);
				for(int i=0; i<len; i++){
					SingleParam param=p.get(i);
					if(param.isCallback()){
						param.getThreadCallBackHandler().run();
					} else {
						ReflectUtil.execMethod(param.getClassName(), param.getMethodName(), param.getParam());
					}
				}
			}
		});
		return thread;
	}
	
	protected static SingleThread getDbTransactionThread(String dbName, final MutiParam params){
		final int len=params.size();
		if(len<1) return null;
		Vector<Object> plist=new Vector<Object>();
		plist.add(params.getParam());
		SingleThread thread=new SingleThread(params.getName(),new TransactionThreadCallBack(dbName, plist){
			protected void run(SqlSession cn, Vector<Object> arg) throws Exception{
				Vector<SingleParam> p=(Vector<SingleParam>) arg.get(0);
				for(int i=0; i<len; i++){
					SingleParam param=p.get(i);
					if(param.isCallback()){
						param.getThreadCallBackHandler().run();
					} else {
						ReflectUtil.execMethod(param.getClassName(), param.getMethodName(), param.getParam());
					}
				}
			}
		});
		return thread;
	}
	
	//单次操作，多线程，用于压缩执行时间并发执行同一操作
    public static Vector<SingleThread> getThread(final ListParam params) throws Exception{
    	Vector<SingleThread> list=new Vector<SingleThread>();
    	final int len=params.size();
    	if(len<1) return null; 
    	final Object obj=ReflectUtil.getObject(params.getClassName());
    	for(int i=0; i<len; i++){
    		String name=params.getName();
    		if(params.getParam(i).size()>0){
    			name=name+"["+(String) params.getParam(i).get(0)+"]";
    		}
    		SingleThread  thread=new SingleThread(name,new ParamThreadCallBack(params.getParam(i)){
    			protected void run(Vector<Object> p) throws Exception {
    				ReflectUtil.execMethod(obj, params.getMethodName(), p);
    			}
    		});
    		list.add(thread);
    	}
    	return list;
	}
    
    public static Vector<SingleThread> getDBThread(String dbName, String type, ListParam params) throws Exception{
		switch(type){
			case "saveTransaction":
				return getDbSaveTransactionThread(dbName, params);
			case "readonly":
				return getDbReadOnlyThread(dbName, params);
			default:
				return getDbTransactionThread(dbName, params);
		}
	}
    
    
    protected static Vector<SingleThread> getDbReadOnlyThread(String dbName, final ListParam params) throws Exception{
    	Vector<SingleThread> list=new Vector<SingleThread>();
    	final int len=params.size();
    	if(len<1) return null; 
    	final Object obj=ReflectUtil.getObject(params.getClassName());
    	for(int i=0; i<len; i++){
    		String name=params.getName();
    		if(params.getParam(i).size()>0){
    			name=name+"["+(String) params.getParam(i).get(0)+"]";
    		}
    		SingleThread  thread=new SingleThread(name,new ReadonlyThreadCallBack(dbName, params.getParam(i)){
    			protected void run(SqlSession cn, Vector<Object> p) throws Exception{
    				ReflectUtil.execMethod(obj, params.getMethodName(), p);
    			}
    		});
    		list.add(thread);
    	}
    	return list;
	}
    
    protected static Vector<SingleThread> getDbTransactionThread(String dbName, final ListParam params) throws Exception{
    	Vector<SingleThread> list=new Vector<SingleThread>();
    	final int len=params.size();
    	if(len<1) return null;
    	final Object obj=ReflectUtil.getObject(params.getClassName());
    	for(int i=0; i<len; i++){
    		String name=params.getName();
    		if(params.getParam(i).size()>0){
    			name=name+"["+(String) params.getParam(i).get(0)+"]";
    		}
    		SingleThread  thread=new SingleThread(name,new TransactionThreadCallBack(dbName, params.getParam(i)){
    			protected void run(SqlSession cn, Vector<Object> p) throws Exception{
    				ReflectUtil.execMethod(obj, params.getMethodName(), p);
    			}
    		});
    		list.add(thread);
    	}
    	return list;
	}
	
    protected static Vector<SingleThread> getDbSaveTransactionThread(String dbName, final ListParam params) throws Exception{
    	Vector<SingleThread> list=new Vector<SingleThread>();
    	final int len=params.size();
    	if(len<1) return null; 
    	final Object obj=ReflectUtil.getObject(params.getClassName());
    	for(int i=0; i<len; i++){
    		String name=params.getName();
    		if(params.getParam(i).size()>0){
    			name=name+"["+(String) params.getParam(i).get(0)+"]";
    		}
    		SingleThread  thread=new SingleThread(name,new SaveTransactionThreadCallBack(dbName, params.getParam(i)){
    			protected Savepoint run(SqlSession cn, Vector<Object> p) throws Exception{
    				return (Savepoint) ReflectUtil.execMethod(obj, params.getMethodName(), p);
    			}
    		});
    		list.add(thread);
    	}
    	return list;
	}
    

}
